home *** CD-ROM | disk | FTP | other *** search
/ Power CD / Power CD ATARI-Rechner Lieben.iso / SPEZIAL / GEMVIEW / VERSION.3 / MODULS.SRC / LOADMODL / IFF.C < prev    next >
Encoding:
C/C++ Source or Header  |  1993-10-15  |  17.2 KB  |  543 lines

  1. /* IFF images
  2.  *
  3.  * dieter fiebelkorn 13.05.91
  4.  *
  5.  */
  6.  
  7.  
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <ctype.h>
  12. #include <math.h>
  13. #include <vdi.h>
  14. #include <aes.h>
  15. #include "image.h"
  16. #include "imageopt.h"
  17. #include "module.h"
  18. #include "iff.h"
  19.  
  20. extern char *DupString(LOAD_Structure *loadS, char *s);
  21.  
  22.  
  23. COLOR_ENTRY    color_map[256];
  24.  
  25. static int loadIffMonoCompressed(ZFILE *zf, LOAD_Structure *loadS, char *data,
  26.                                  unsigned int width, unsigned int height)
  27. {
  28.   unsigned char  wert, run;
  29.   signed char    command;
  30.   long           read, toRead;
  31.   
  32.   toRead = (width >> 3) + ((width & 0x0007) ? 1 : 0);
  33.   toRead *= height;
  34.   read = 0UL;
  35.   do {
  36.     command = (signed char) (*loadS->input.getchr)(zf);
  37.     if (command == -128) {
  38.       (*loadS->input.close)(zf);
  39.       (*loadS->print.printout)("DegasLoad: Bad read on image data\n");
  40.       return(-1);
  41.     }
  42.     if (command < 0) {
  43.       wert = (unsigned char) (*loadS->input.getchr)(zf);
  44.       for (run = 0; run < -command+1; run++, read++)
  45.         *data++ = wert;
  46.     }
  47.     else {
  48.       for (run = 0; run < command+1; run++, read++) {
  49.         wert = (unsigned char) (*loadS->input.getchr)(zf);
  50.         *data++ = wert;
  51.       }
  52.     }
  53.   } while (read < toRead);
  54.   return(0);
  55. }
  56.  
  57.  
  58.  
  59. static int loadIffColorCompressed(ZFILE *zf, LOAD_Structure *loadS, char *data,
  60.                                   unsigned int width, unsigned int height,
  61.                                   unsigned int planes, unsigned int ismask)
  62. {
  63.   unsigned char  wert, run,
  64.                  buffer[BUFSIZ];
  65.   signed char    command, warning;
  66.   long           read;
  67.   unsigned long  x, y, plane, offs;
  68.   unsigned long  set_bit, mask;
  69.   
  70.   warning = '\0';
  71.   for (y= 0; y < height; y++) {
  72.     for (plane= 0; plane < planes+(ismask!=0); plane++) {
  73.       read = 0UL;
  74.       do {
  75.         command = (signed char) (*loadS->input.getchr)(zf);
  76.         if (command == -128)
  77.           continue;
  78.         
  79.         if (command < 0) {
  80.           wert = (unsigned char) (*loadS->input.getchr)(zf);
  81.           for (run = 0; run < -command+1; run++, read++)
  82.             buffer[read] = wert;
  83.         }
  84.         else {
  85.           for (run = 0; run < command+1; run++, read++) {
  86.             wert = (unsigned char) (*loadS->input.getchr)(zf);
  87.             buffer[read] = wert;
  88.           }
  89.         }
  90.       } while (read < width/8);
  91.   
  92.       if (read > width/8 && warning == '\0')
  93.       {
  94.         (*loadS->print.printout)("  \034\001Warning:\034\100 Incorrect length of decoded scanline\n");
  95.         warning = '\x01';
  96.       }
  97.       
  98.       if (plane < planes) {
  99.         set_bit = 1U << plane;
  100.         for (x= 0; x < width/8; x++) {
  101.           mask = 0x80;
  102.           offs = 0;
  103.           do {
  104.             if (buffer[x] & mask)
  105.               data[8UL * x + offs] |= set_bit;
  106.             mask >>= 1;
  107.             offs++;
  108.           } while(mask);
  109.         }
  110.       }
  111.     }
  112.     data += width;
  113.   }
  114.   return(0);
  115. }
  116.  
  117.  
  118.  
  119. static void loadIffMonoUnCompressed(ZFILE *zf, LOAD_Structure *loadS, char *data,
  120.                                     unsigned int width, unsigned int height)
  121. {
  122.   unsigned long  toRead;
  123.   
  124.   toRead = (width >> 3) + ((width & 0x0007) ? 1 : 0);
  125.   toRead *= height;
  126.   (*loadS->input.read)(zf, data, toRead);
  127. }
  128.  
  129.  
  130.  
  131. static int loadIffColorUnCompressed(ZFILE *zf, LOAD_Structure *loadS, char *data,
  132.                                     unsigned int width, unsigned int height,
  133.                                     unsigned int planes, unsigned int ismask)
  134. {
  135.   long           x, y;
  136.   unsigned int   buffer, plane;
  137.   unsigned int   mask, offs;
  138.   
  139.   for (y= 0; y < height; y++) {
  140.     for (plane= 0; plane < planes+(ismask!=0); plane++) {
  141.       for (x= 0; x < width/16; x++) {
  142.         if ((*loadS->input.read)(zf, &buffer, 2UL) < 2UL) {
  143.           (*loadS->error.printerr)("  Error reading IFF!");
  144.           (*loadS->input.close)(zf);
  145.           return(-1);
  146.         }
  147.         if (plane < planes) {
  148.           mask = 0x8000;
  149.           offs = 0;
  150.           while (mask) {
  151.             if (buffer & mask)
  152.               data[16*x + offs] |= 1U << plane;
  153.             mask >>= 1;
  154.             offs++;
  155.           }
  156.         }
  157.       }
  158.     }
  159.     data += width;
  160.   }
  161.   return(0);
  162. }
  163.  
  164.  
  165.  
  166. static loadIffHam(ZFILE *zf, LOAD_Structure *loadS, char *data,
  167.                   unsigned int width, unsigned int height, unsigned int alignwidth,
  168.                   unsigned int planes, unsigned int compressed)
  169. {
  170.   COLOR_ENTRY    color;
  171.   unsigned char *new_data;
  172.   unsigned int   skip, x, y;
  173.   unsigned int   op_shift, col_shift;
  174.   unsigned char  op, col, col_mask;
  175.   
  176.   new_data = data + 2L * width * height;
  177.   if (compressed)
  178.     loadIffColorCompressed(zf, loadS, new_data, width, height, planes, 0);
  179.   else
  180.     loadIffColorUnCompressed(zf, loadS, new_data, width, height, planes, 0);
  181.   
  182.   if (planes != 6 && planes != 8)
  183.     return(0);
  184.  
  185.   color.red   = 0;
  186.   color.green = 0;
  187.   color.blue  = 0;
  188.  
  189.   if (planes == 6) {
  190.     op_shift = 4;
  191.     col_mask = 0x0F;
  192.     col_shift = 4;
  193.   }
  194.   if (planes == 8) {
  195.     op_shift = 6;
  196.     col_mask = 0x3F;
  197.     col_shift = 2;
  198.   }
  199.   
  200.   skip = alignwidth - width;
  201.   for (y= 0; y < height; y++) {
  202.     for (x= 0; x < width; x++) {
  203.       op = *new_data >> op_shift;
  204.       col = *new_data & col_mask;
  205.       if (op == 0) {
  206.         color.red   = color_map[(int)col].red;
  207.         color.green = color_map[(int)col].green;
  208.         color.blue  = color_map[(int)col].blue;
  209.       }
  210.       if (op == 2) {
  211.         color.red   = col << col_shift;
  212.       }
  213.       if (op == 3) {
  214.         color.green = col << col_shift;
  215.       }
  216.      if (op == 1) {
  217.         color.blue  = col << col_shift;
  218.       }
  219.       *data++ = color.red;
  220.       *data++ = color.green;
  221.       *data++ = color.blue;
  222.       new_data++;
  223.     }
  224.     data += 3L * skip;
  225.   }
  226.   return(0);
  227. }
  228.  
  229.  
  230.  
  231. int iffIdent(LOAD_Structure *loadS, unsigned int verbose)
  232. {
  233.   ZFILE         *zf;
  234.   IFF_HEADER     iffheader;
  235.   CHUNK_HEADER   chunkheader;
  236.   BITMAP_HEADER  bitmapheader;
  237.   int            found_camgchunk,
  238.                  found_bitmapheader;
  239.   long           i;
  240.   char          *fullname = loadS->in_filename;
  241.   
  242.   if ((zf= (*loadS->input.open)(fullname, 0x00)) != NULL) {
  243.     (*loadS->input.read)(zf, &iffheader, sizeof(iffheader));
  244.     
  245.     while ((*(long*)&iffheader.form_id == 'FORM') && (*(long*)&iffheader.file_id != 'ILBM')) {
  246.       (*loadS->input.skip)(zf, iffheader.lenght);
  247.       if ((*loadS->input.read)(zf, &iffheader, sizeof(iffheader)) != sizeof(iffheader)) {
  248.         (*loadS->input.close)(zf);
  249.         return(0);
  250.       }
  251.     }
  252.     if ((*(long*)&iffheader.form_id != 'FORM') || (*(long*)&iffheader.file_id != 'ILBM')) {
  253.       (*loadS->input.close)(zf);
  254.       return(0);
  255.     }
  256.  
  257.     found_camgchunk = 0;
  258.     found_bitmapheader = 0;
  259.  
  260.     while(1) {
  261.       (*loadS->input.read)(zf, &chunkheader, sizeof(chunkheader));
  262.       if ((!isupper(chunkheader.chunk_id[0]) && chunkheader.chunk_id[0] != ' ') ||
  263.           (!isupper(chunkheader.chunk_id[1]) && chunkheader.chunk_id[1] != ' ') ||
  264.           (!isupper(chunkheader.chunk_id[2]) && chunkheader.chunk_id[2] != ' ') ) {
  265.         (*loadS->error.printerr)("  Error reading IFF!");
  266.         break;
  267.       }
  268.       if (*(long*)&chunkheader.chunk_id == 'CAMG') {
  269.         (*loadS->input.read)(zf, &i, sizeof(long));
  270.         if (i & 0x00000800L)
  271.           found_camgchunk = 1;
  272.         continue;
  273.       }
  274.       if (*(long*)&chunkheader.chunk_id == 'BMHD')
  275.       {
  276.         (*loadS->input.read)(zf, &bitmapheader, sizeof(bitmapheader));
  277.         found_bitmapheader = 1;
  278.         continue;
  279.       }
  280.       if (*(long*)&chunkheader.chunk_id == 'BODY')
  281.       {
  282.         if (bitmapheader.planes == 1)
  283.           (*loadS->print.printout)("%s\n  is a %dx%d monochrome/duochrome IFF-image\n", fullname,
  284.                   bitmapheader.width, bitmapheader.height);
  285.         else
  286.           if (found_camgchunk == 1 && (bitmapheader.planes == 6 || bitmapheader.planes == 8))
  287.             (*loadS->print.printout)("%s\n  is a %dx%d HAM-IFF-image\n", fullname,
  288.                     bitmapheader.width, bitmapheader.height);
  289.           else
  290.             (*loadS->print.printout)("%s\n  is a %dx%d IFF-image with %d colors\n", fullname,
  291.                     bitmapheader.width, bitmapheader.height, 1U << bitmapheader.planes);
  292.  
  293.         (*loadS->input.close)(zf);
  294.         return(found_bitmapheader);
  295.       }
  296.       (*loadS->input.skip)(zf, chunkheader.lenght);
  297.     }
  298.   }
  299.   (*loadS->input.close)(zf);
  300.   return(0);
  301. }
  302.  
  303.  
  304.  
  305. Image *iffLoad(LOAD_Structure *loadS, unsigned int verbose)
  306. {
  307.   ZFILE         *zf;
  308.   Image         *image = NULL;
  309.   IFF_HEADER     iffheader;
  310.   CHUNK_HEADER   chunkheader;
  311.   BITMAP_HEADER  bitmapheader;
  312.   int            found_bitmapheader;
  313.   int            found_camgchunk;
  314.   int            found_cmapchunk;
  315.   int            bw_pict;
  316.   long           map_colors, colors,
  317.                  max_colors, i;
  318.   unsigned long  factor;
  319.   char          *fullname = loadS->in_filename;
  320.   int            id_only  = loadS->identify_only;
  321.   
  322.   found_bitmapheader = 0;
  323.   map_colors         = 0;
  324.   max_colors         = 8;
  325.   
  326.   if (id_only)
  327.     return((Image*)iffIdent(loadS, verbose));
  328.   
  329.   if (iffIdent(loadS, verbose) == 0)
  330.     return(NULL);
  331.   
  332.   if ((zf= (*loadS->input.open)(fullname, 0x00)) == 0) {
  333.     (*loadS->error.printerr)("  Error reading IFF!");
  334.     return(NULL);
  335.   }
  336.   (*loadS->input.read)(zf, &iffheader, sizeof(iffheader));
  337.   while ((*(long*)&iffheader.form_id == 'FORM') && (*(long*)&iffheader.file_id != 'ILBM')) {
  338.     (*loadS->input.skip)(zf, iffheader.lenght);
  339.     if ((*loadS->input.read)(zf, &iffheader, sizeof(iffheader)) != sizeof(iffheader)) {
  340.       (*loadS->input.close)(zf);
  341.       return(0);
  342.     }
  343.   }
  344.   
  345.   found_bitmapheader = 0;
  346.   found_camgchunk = 0;
  347.   found_cmapchunk = 0;
  348.   while (1) {
  349.     (*loadS->input.read)(zf, &chunkheader, sizeof(chunkheader));
  350.     if ((!isupper(chunkheader.chunk_id[0]) && chunkheader.chunk_id[0] != ' ') ||
  351.         (!isupper(chunkheader.chunk_id[1]) && chunkheader.chunk_id[1] != ' ') ||
  352.         (!isupper(chunkheader.chunk_id[2]) && chunkheader.chunk_id[2] != ' ') ) {
  353.       (*loadS->error.printerr)("  Error reading IFF!");
  354.       if (image)
  355.         (*loadS->images.freeGVImage)(image);
  356.       image = NULL;
  357.       (*loadS->input.close)(zf);
  358.       return(image);
  359.     }
  360.     if (*(long*)&chunkheader.chunk_id == 'BMHD')
  361.     {
  362.       found_bitmapheader = 1;
  363.       (*loadS->input.read)(zf, &bitmapheader, sizeof(bitmapheader));
  364.       if (bitmapheader.planes > 8) {
  365.         (*loadS->print.printout)("  Don't support more then 8 planes");
  366.         (*loadS->input.close)(zf);
  367.         return(NULL);
  368.       }
  369.       if (bitmapheader.compressed > 1) {
  370.         (*loadS->print.printout)("  Don't supported compression algorithm");
  371.         (*loadS->input.close)(zf);
  372.         return(NULL);
  373.       }
  374.       if ((bitmapheader.planes == 1) && (bitmapheader.mask & 0x01)) {
  375.         (*loadS->print.printout)("  Don't support monochrome Images with _mask_");
  376.         (*loadS->input.close)(zf);
  377.         return(NULL);
  378.       }
  379.       continue;
  380.     }
  381.     if (*(long*)&chunkheader.chunk_id == 'CMAP')
  382.     {
  383.       map_colors = chunkheader.lenght / 3;
  384.       if (map_colors > 256) {
  385.         (*loadS->print.printout)("  Don't support more then 256 colors");
  386.         (*loadS->input.close)(zf);
  387.         return(NULL);
  388.       }
  389.       found_cmapchunk = 1;
  390.       if (map_colors <= 2)
  391.         bw_pict = 1;
  392.       for (i = 0; i < map_colors; i++) {
  393.         (*loadS->input.read)(zf, &(color_map[i]), 3UL /*sizeof(COLOR_ENTRY)*/);
  394.         if (max_colors < 256) {
  395.           if (max_colors < 16) {
  396.             if ((color_map[i].red > 7) || (color_map[i].green > 7) || (color_map[i].blue > 7))
  397.               max_colors = 16;
  398.           }
  399.           if ((color_map[i].red > 15) || (color_map[i].green > 15) || (color_map[i].blue > 15))
  400.             max_colors = 256;
  401.         }
  402.         if (bw_pict == 1) {
  403.           switch((int)max_colors)
  404.           {
  405.             case   8:
  406.               bw_pict &= (color_map[i].red >= 7 && color_map[i].green >= 7 && color_map[i].blue >= 7)
  407.                       || (color_map[i].red <= 0 && color_map[i].green <= 0 && color_map[i].blue <= 0);
  408.               break;
  409.             case  16:
  410.               bw_pict &= (color_map[i].red >= 15 && color_map[i].green >= 15 && color_map[i].blue >= 15)
  411.                       || (color_map[i].red <=  0 && color_map[i].green <=  0 && color_map[i].blue <=  0);
  412.               break;
  413.             case 256:
  414.               bw_pict &= (color_map[i].red >= 254 && color_map[i].green >= 254 && color_map[i].blue >= 254)
  415.                       || (color_map[i].red <=   0 && color_map[i].green <=   0 && color_map[i].blue <=   0);
  416.               break;
  417.           }
  418.         }
  419.       }
  420.       continue;
  421.     }
  422.     if (*(long*)&chunkheader.chunk_id == 'CAMG') {
  423.       (*loadS->input.read)(zf, &i, sizeof(long));
  424.       if (i & 0x00000800L)
  425.         found_camgchunk = 1;
  426.       continue;
  427.     }
  428.  
  429.     if (*(long*)&chunkheader.chunk_id == 'BODY') {
  430.       if (found_bitmapheader) {
  431.         if (bitmapheader.planes == 1 && (found_cmapchunk == 0 || bw_pict != 0)) {
  432.           if ((bitmapheader.width == 0) ||
  433.               (bitmapheader.height == 0)) {
  434.             (*loadS->input.close)(zf);
  435.             return (NULL);
  436.           }
  437.           
  438.           image = (*loadS->images.newBitImage)(NULL, (unsigned int) bitmapheader.width, (unsigned int) bitmapheader.height);
  439.           if (!image) {
  440.             (*loadS->input.close)(zf);
  441.             return (image);
  442.           }
  443.           
  444.           if (bitmapheader.width % 16)
  445.           {
  446.             image->unalignwidth = bitmapheader.width;
  447.             image->width = (bitmapheader.width += 16 - (bitmapheader.width % 16));
  448.           }
  449.           if (bitmapheader.compressed)
  450.             loadIffMonoCompressed(zf, loadS, image->data, bitmapheader.width, bitmapheader.height);
  451.           else
  452.             loadIffMonoUnCompressed(zf, loadS, image->data, bitmapheader.width, bitmapheader.height);
  453.         }
  454.         else
  455.         {
  456.           if ((bitmapheader.width == 0) ||
  457.               (bitmapheader.height == 0) ||
  458.               (bitmapheader.planes == 0)) {
  459.             (*loadS->input.close)(zf);
  460.             return (NULL);
  461.           }
  462.  
  463.           if (found_camgchunk == 0 || (bitmapheader.planes != 6 && bitmapheader.planes != 8))
  464.             image = (*loadS->images.newRGBImage)(NULL, (unsigned int) bitmapheader.width, (unsigned int) bitmapheader.height, bitmapheader.planes);
  465.           else
  466.             image = (*loadS->images.newTCImage)(NULL, (unsigned int) bitmapheader.width, (unsigned int) bitmapheader.height);
  467.           if (!image) {
  468.             (*loadS->input.close)(zf);
  469.             return (image);
  470.           }
  471.  
  472.           if (bitmapheader.width % 16)
  473.           {
  474.             image->unalignwidth = bitmapheader.width;
  475.             image->width = (bitmapheader.width += 16 - (bitmapheader.width % 16));
  476.           }
  477.  
  478.           if (found_camgchunk == 1 && (bitmapheader.planes == 6 || bitmapheader.planes == 8)) {
  479.             if (loadIffHam(zf, loadS, image->data, bitmapheader.width, bitmapheader.height, image->width, bitmapheader.planes, bitmapheader.compressed)) {
  480.               (*loadS->images.freeGVImage)(image);
  481.               image = NULL;
  482.             }
  483.             if (image)
  484.               image->title= DupString(loadS, fullname);
  485.             (*loadS->input.close)(zf);
  486.             return(image);
  487.           }
  488.           
  489.           image->rgb.red  [ 0]= 0xFF00;
  490.           image->rgb.green[ 0]= 0xFF00;
  491.           image->rgb.blue [ 0]= 0xFF00;
  492.           colors = 1U << bitmapheader.planes;
  493.           switch((int)max_colors)
  494.           {
  495.             case   8:
  496.               factor = 364;
  497.               break;
  498.             case  16:
  499.               factor = 170;
  500.               break;
  501.             case 256:
  502.               factor = 10;
  503.               break;
  504.           }
  505.  
  506.           if (map_colors > colors)
  507.             map_colors = colors;
  508.  
  509. /*        colors -= map_colors;
  510. */        for (i = 0; i < map_colors; i++) {
  511.             image->rgb.red[i]   = ((int) (factor * color_map[i].red   / 10)) << 8;
  512.             image->rgb.green[i] = ((int) (factor * color_map[i].green / 10)) << 8;
  513.             image->rgb.blue[i]  = ((int) (factor * color_map[i].blue  / 10)) << 8;
  514.           }
  515.           image->rgb.used = (int)map_colors;
  516.           for (/* i = 0 */; i < colors; i++) {
  517.             image->rgb.red[i]   = 0x0000;
  518.             image->rgb.green[i] = 0x0000;
  519.             image->rgb.blue[i]  = 0x0000;
  520.           }
  521.           if (bitmapheader.compressed)
  522.             loadIffColorCompressed(zf, loadS, image->data, bitmapheader.width, bitmapheader.height, bitmapheader.planes, bitmapheader.mask & 0x01);
  523.           else
  524.             if (loadIffColorUnCompressed(zf, loadS, image->data, bitmapheader.width, bitmapheader.height, bitmapheader.planes, bitmapheader.mask & 0x01) == -1) {
  525.               (*loadS->images.freeGVImage)(image);
  526.               image = NULL;
  527.               (*loadS->input.close)(zf);
  528.               return(image);
  529.             }
  530.         }
  531.       }
  532.       break;
  533.     }
  534.     (*loadS->input.skip)(zf, chunkheader.lenght);
  535.   }
  536.   
  537.   if (image)
  538.     image->title= DupString(loadS, fullname);
  539.  
  540.   (*loadS->input.close)(zf);
  541.   return(image);
  542. }
  543.